<?php

namespace App\Http\Controllers\Api;

use App\Enum\CityEnableEnum;
use App\Enum\CodeEnum;
use App\Enum\DriverEnum;
use App\Enum\OrderEnum;
use App\Enum\RedisEnum;
use App\Enum\TravelEnum;
use App\Events\OrderCanceled;
use App\Events\OrderCreated;
use App\Models\OrderModel;
use App\Models\VillagerUserModel;
use App\Services\CommonService;
use App\Services\GeoService;
use App\Services\OrderService;
use App\Services\PublikService;
use App\Services\RedisKeysService;
use App\Services\Tools\HelpService;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class OrderController extends ApiBaseController
{
    /**
     * 我的-订单列表
     * @param Request $request
     * @return JsonResponse
     * @author ninetyseven.
     * @date 2023-03-29 23:35
     */
    public function getMyOrderList(Request $request): JsonResponse
    {
        try {
            $userId = $request->userId;
            $typeId = $request->get('type_id') ?? 0;
            $platformId = self::getPlatformId();

            $params = $request->post(); $paramsStr = md5(implode(',',$params));
            // 取redis
            $redisKey = sprintf(OrderEnum::USER_ORDER_LIST_REDIS_KEY,$userId,$typeId,$platformId,$paramsStr);//'getMyOrderList-'.$userId.'-'.$typeId.'-'.$platformId;

            // 参数
            $params = ['userId'=>$userId, 'typeId'=>$typeId,'platformId'=>$platformId];
            if( intval($platformId) !== TravelEnum::PLATFORM_DRIVER) {
                // 分页处理
                $params['perPage'] = true;
            }else{
                // 无分页处理
                $params['perPage'] = false;
            }
            $data = self::_cacheableData($redisKey, OrderEnum::USER_ORDER_LIST_REDIS_TIMEOUT, (new OrderService()), 'getMyOrderList',$params, $request,true );

            // 存储订单列表key,用于统一删除
            (new RedisKeysService())->addOrderListKey($userId, $redisKey);

            return success($data);
        } catch (Exception|NotFoundExceptionInterface|ContainerExceptionInterface $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    /**
     * 司机的待处理订单列表
     *
     * @param Request $request
     * @return JsonResponse
     */
    public function getWaitOrderList(Request $request): JsonResponse
    {
        try {

            $redisKey = sprintf(DriverEnum::R_DRIVER_WAIT_ORDER_LIST_KEY, $request->userId);
            $data = self::_cacheableData($redisKey, DriverEnum::R_DRIVER_WAIT_ORDER_LIST_TTL, (new OrderService()), 'getWaitOrderList', $request->userId, $request, true);
//            $data = OrderService::getWaitOrderList($request->userId);
            // 添加到keys中
            (new RedisKeysService())->addDriverWaitOrderListKey($request->userId, $redisKey);
            return success($data);
        } catch (Exception|NotFoundExceptionInterface|ContainerExceptionInterface $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    /**
     * 居委会/村委会-订单列表
     * getCommunityList
     * @param Request $request
     * @return JsonResponse|null
     * @author ninetyseven.
     * @date 2023/5/2
     */
    public function getCommunityList(Request $request): ?JsonResponse
    {
        try {
            $userId = $request->userId;
            $typeId = $request->get('type_id') ?? 0;
            $platformId = self::getPlatformId();

            $data = OrderService::getCommunityList($userId, $typeId, $platformId);
            return success(HelpService::resultsPage($data));
        } catch (Exception $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    /**
     * 首页-订单列表
     * @param Request $request
     * @return JsonResponse
     * @author ninetyseven.
     * @date 2023-03-30 22:53
     */
    public function getIndexOrderList(Request $request): JsonResponse
    {
        try {
            $typeId = $request->get('type_id') ?? 0;

            $data = OrderService::getIndexOrderList($typeId,self::getPlatformId());
            return success(HelpService::resultsPage($data));
        } catch (Exception $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    /**
     * 统计待出行订单
     * @return JsonResponse
     * @author ninetyseven.
     * @date 2023-03-29 0:44
     */
    public function getPendingTravel(): JsonResponse
    {
        $userId = \request()->userId;

        $data = OrderService::getWaitOrderNum($userId);
        if (!$data) {
            return fail(CodeEnum::ERROR, '暂无待出行订单数据');
        }
        return success($data);
    }

    /**
     * 我的-统计服务订单数(司机)
     * @author ninetyseven.
     * @date 2023-04-02 14:14
     */
    public function countDriverOrder(): array
    {
        $userId = \request()->userId;
        return OrderService::getOrderDriverNum($userId);
    }

    /**
     * 我的-统计服务订单数(志愿者)
     * @author ninetyseven.
     * @date 2023-04-02 14:14
     */
    public function countVolunteerOrder(): array
    {
        $userId = \request()->userId;
        return OrderService::getOrderVolunteerNum($userId);
    }

    /**
     * 统计订单.
     * @author ninetyseven.
     * @date 2023-04-15 15:05
     */
    public function countOrder(): JsonResponse
    {
        $platformId = self::getPlatformId();
        $data = [];
        switch ($platformId) {
            case TravelEnum::PLATFORM_VOLUNTEER:
                $data = $this->countVolunteerOrder();
                break;
            case TravelEnum::PLATFORM_DRIVER:
                $data = $this->countDriverOrder();
                break;
        }
        return success($data);
    }

    /**
     * 创建订单列表
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     * @author ninetyseven.
     * @date 2023-03-29 23:42
     */
    public function addOrder(Request $request): JsonResponse
    {
        try {
            // 验证手机号通过
            parent::validUserAccess($request->userId);

            // 验证城市来源，转为合法数据（直辖市code降级）
            $cityCode = self::_validCitySource($request);

            // 验证地址 与城市的一致性
            self::_validAddressInCity($request,$cityCode);

            // 验证围栏 围栏默认关闭，城市围栏默认开启
            if( env('ENABLE_WEILAN',false)  && env('ENABLE_WEILAN_'.$cityCode, true) )
                self::validCityFence($cityCode, $request);

            $orderInfo = OrderService::addOrder($request,self::getPlatformId());

            // 触发订单取消成功后的事件20230821 by LC
           event(new OrderCreated($orderInfo));

            return success($orderInfo);
        } catch (Exception $e) {
            $code = $e->getCode()??CodeEnum::ERROR;
            return fail($code, $e->getMessage());
        }
    }

    /**
     * 修改订单列表
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     * @author ninetyseven.
     * @date 2023-03-29 23:42
     */
    public function updateOrder(Request $request): JsonResponse
    {
        try {
            DB::beginTransaction();
            $res = OrderService::updateOrder($request);
            if(!$res){
                throw new Exception('修改失败');
            }
            DB::commit();
            return success();
        } catch (Exception $e) {
            DB::rollBack();
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    public function checkOrder(Request $request): JsonResponse
    {
        try {
            $res = OrderService::checkOrder($request);
            return success($res);
        } catch (Exception $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    /**
     * 订单详情
     * @param Request $request
     * @return JsonResponse
     * @author ninetyseven.
     * @date 2023-04-05 13:15
     */
    public function getOrderInfo(Request $request): JsonResponse
    {
        try {
            $orderId = $request->get('order_id');
            if (!$orderId) {
                throw new Exception('订单id不存在');
            }
            $res = OrderService::getOrderInfo($orderId);
            return success($res);
        } catch (Exception $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }
    /**
     * 获取往返订单详情
     */
    public function getOrderInfoGoAndBack(Request $request): JsonResponse
    {
        try {
            $orderId = $request->get('order_id');
            if (!$orderId) {
                throw new Exception('订单id不存在');
            }
            $orderInfo = OrderService::getOrderInfo($orderId);
            $res = [$orderInfo];
            // 如果是往返订单则把回程订单信息给到，仅志愿者可以获取订单数组
            if( $orderInfo['is_return'] == OrderEnum::ORDER_RETURN_CODE && self::getPlatformId() == TravelEnum::PLATFORM_VOLUNTEER){
                if( empty($orderInfo['go_order_id']) ){ // 当前订单是去程订单
                    $otherOrderId = OrderModel::query()->where('go_order_id',$orderInfo['id'])->value('id');
                    $res[] = OrderService::getOrderInfo($otherOrderId);
                }
            }
            return success($res);
        } catch (Exception $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }
    /**
     * 用户评价
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     * @author ninetyseven.
     * @date 2023-03-29 23:42
     */
    public function appraiseOrder(Request $request): JsonResponse
    {
        try {
            $res = OrderService::appraiseOrder($request);
            return success($res);
        } catch (Exception $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    /**
     * 订单状态修改
     * @param Request $request
     * @return JsonResponse
     * @throws Exception
     * @throws GuzzleException
     * @author ninetyseven.
     */
    public function updateOrderCancel(Request $request): JsonResponse
    {
        try {
            DB::beginTransaction();

            $orderInfo = OrderService::cancelOrderStatus($request->id);
            if( empty($orderInfo) ){
                return fail(CodeEnum::ERROR, $orderInfo);
            }
            $adminInfo = [
                'admin_id'      => $request->admin_id,
                'admin_name'    => $request->admin_name
            ];
            // 去掉用户订单的缓存 20230926 by LC
            (new RedisKeysService())->deleteOrderListKey($orderInfo['user_id'],$orderInfo['driver_id']);

            // 触发订单取消成功后的事件20230821 by LC
            event(new OrderCanceled($orderInfo,$adminInfo, $orderInfo->old_status));
            // 异步处理event事件 20230927 by LC
//            Event::fire(new OrderCanceledAsyncEvent($orderInfo,$adminInfo));
            DB::commit();
            return success();
        } catch (Exception $e) {
            DB::rollBack();
            return fail(CodeEnum::ERROR, $e->getMessage());
        } catch (NotFoundExceptionInterface|ContainerExceptionInterface $e) {
            DB::rollBack();
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    /**
     * 预计扣除
     * @param Request $request
     * @return JsonResponse
     * @author ninetyseven.
     * @date 2023-04-05 13:15
     */
    public function expectedDeduction(Request $request): JsonResponse
    {
        try {
            if (!in_array($request->payment,array_keys(OrderEnum::ORDER_PAY_KEYS))) {   throw new Exception('支付方式非法：payment');}
            if( empty($request->vehicle_type) || empty($request->vehicle_use_type) || empty($request->km_num) || empty($request->city_code)){
                throw new Exception('参数不正确。');
            }
            $res = OrderService::expectedDeduction($request,OrderEnum::ORDER_PAY_KEYS[$request->payment]);
            return success($res);
        } catch (Exception $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }

    /**
     * 获取订单列表
     * getInfo
     * @return JsonResponse|null
     * @author ninetyseven.
     * @date 2023/5/3
     */
    public function getInfo(): ?JsonResponse
    {
        try {
            $res = OrderService::getInfo();
            return success($res);
        } catch (Exception $e) {
            return fail(CodeEnum::ERROR, $e->getMessage());
        }
    }
    private function validCityFence(int $cityCode, Request $request)
    {
        try {
            $location  = explode(',',$request->start_location);
            $points[] = $location[1].','.$location[0];
            $location  = explode(',',$request->end_location);
            $points[] = $location[1].','.$location[0];

            // 围栏默认关闭，城市围栏默认开启
            GeoService::isPointsAvailable($points, $cityCode);

        }catch (Exception $e){
            Log::notice("电子围栏验证失败：".$e->getMessage());
            throw new Exception("您的用车上/下车点包含禁用区域，请重新选择后下单。");
        }
    }

    /**
     *  验证地址 与城市的一致性getCityDistricts
     *
     * @param $request
     * @param $cityCode
     * @return void
     * @throws Exception
     */
    private function _validAddressInCity($request,$cityCode)
    {
        $redisKey = sprintf(RedisEnum::R_CITY_DISTRICTS_KEY, $cityCode);
        $result = $this->_cacheableData($redisKey, RedisEnum::R_CITY_DISTRICTS_TO, (new PublikService()),'getCityDistricts', $cityCode, $request );

        $districts = explode(',', $result);
        if( !in_array($request->start_adcode, $districts) ) throw new Exception(sprintf("开始地址的区县编号(%s)与城市编号(%s)不匹配", $cityCode, var_export($districts,true)) );
        if( !in_array($request->end_adcode, $districts) ) {
            Log::notice(sprintf("目的地址的区县编号(%s)与城市编号(%s)不匹配", $cityCode, var_export($districts,true)));
//            throw new Exception("目的地址的区县编号与城市编号不匹配");
        }
    }

}
